#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <qmenu.h>
#include <qstyleoption.h>
#include "weathertool.h"

#define INCREMENT 3    //温度每升高/降低一℃，曲线绘制坐标上升/下降INCREMENT像素
#define POINT_RADIUS 3 //曲线点的大小（半径）
#define TEXT_OFFSET_X 12 //绘制温度文本时根据点偏移距离
#define TEXT_OFFSET_Y 12 //

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //1窗口属性
    setWindowFlag(Qt::FramelessWindowHint); //设置窗口无边框
    setFixedSize(width(),height());         //设置固定窗口大小

    //2构建右键菜单
    mExitMenu = new QMenu(this);
    mExitAct = new QAction();

    mExitAct->setText("退出");
    mExitAct->setIcon(QIcon(":/image/close.png"));

    mExitMenu->addAction(mExitAct);

    connect(mExitAct, &QAction::triggered, [=](){//点击菜单项退出
        qApp->exit(0);
    });

//    setAttribute(Qt::WA_TranslucentBackground); //圆角窗口
//    this->setStyleSheet("QMainWindow{background-color:grey;border-radius:15px}");

    //将控件添加到控件数组
    mWeekList << ui->lblWeek_1<< ui->lblWeek_2<< ui->lblWeek_3<< ui->lblWeek_4<< ui->lblWeek_5<< ui->lblWeek_6;
    mDateList << ui->lblDate_1<< ui->lblDate_2<< ui->lblDate_3<< ui->lblDate_4<< ui->lblDate_5<< ui->lblDate_6;
    mTypeList << ui->lblType_2<< ui->lblType_3<< ui->lblType_4<< ui->lblType_5<< ui->lblType_6<< ui->lblType_7;
    mTypeIconList << ui->lblTypeIcon1_1<< ui->lblTypeIcon1_2<< ui->lblTypeIcon1_3<< ui->lblTypeIcon1_4<< ui->lblTypeIcon1_5<< ui->lblTypeIcon1_6;
    mAqiList << ui->lblQuality1_1<< ui->lblQuality1_2<< ui->lblQuality1_3<< ui->lblQuality1_4<< ui->lblQuality1_5<< ui->lblQuality1_6;
    mFxList << ui->lblFX1_1<< ui->lblFX1_2<< ui->lblFX1_3<< ui->lblFX1_4<< ui->lblFX1_5<< ui->lblFX1_6;
    mFlList << ui->lblFL_1<< ui->lblFL_2<< ui->lblFL_3<< ui->lblFL_4<< ui->lblFL_5<< ui->lblFL_6;

    //天气数据与图片相关联
    mTypeMap.insert("暴雪", ":/image/type/BaoXue.png");
    mTypeMap.insert("暴雨", ":/image/type/BaoYu.png");
    mTypeMap.insert("暴雨到大暴雨", ":/image/type/BaoYuDaoDaBaoYu.png");
    mTypeMap.insert("大暴雨", ":/image/type/DaBaoYu.png");
    mTypeMap.insert("大暴雨到特大暴雨", ":/image/type/DaBaoYuDaoTeDaBaoYu.png");
    mTypeMap.insert("大到暴雪", ":/image/type/DaDaoBaoXue.png");
    mTypeMap.insert("大雪", ":/image/type/DaXue.png");
    mTypeMap.insert("大雨", ":/image/type/DaYu.png");
    mTypeMap.insert("冻雨", ":/image/type/DongYu.png");
    mTypeMap.insert("多云", ":/image/type/DuoYun.png");
    mTypeMap.insert("浮沉", ":/image/type/FuChen.png");
    mTypeMap.insert("雷阵雨", ":/image/type/LeiZhenYu.png");
    mTypeMap.insert("雷阵雨伴有冰雹", ":/image/type/LeiZhenYuBanYouBingBao.png");
    mTypeMap.insert("霾", ":/image/type/Mai.png");
    mTypeMap.insert("强沙尘暴", ":/image/type/QiangShaChenBao.png");
    mTypeMap.insert("晴", ":/image/type/Qing.png");
    mTypeMap.insert("沙尘暴", ":/image/type/ShaChenBao.png");
    mTypeMap.insert("特大暴雨", ":/image/type/TeDaBaoYu.png");
    mTypeMap.insert("undefined", ":/image/type/undefined.png");
    mTypeMap.insert("雾", ":/image/type/Wu.png");
    mTypeMap.insert("小到中雪", ":/image/type/XiaoDaoZhongXue.png");
    mTypeMap.insert("小到中雨", ":/image/type/XiaoDaoZhongYu.png");
    mTypeMap.insert("小雪", ":/image/type/XiaoXue.png");
    mTypeMap.insert("小雨", ":/image/type/XiaoYu.png");
    mTypeMap.insert("雪", ":/image/type/Xue.png");
    mTypeMap.insert("扬沙", ":/image/type/YangSha.png");
    mTypeMap.insert("阴", ":/image/type/Yin.png");
    mTypeMap.insert("雨", ":/image/type/Yu.png");
    mTypeMap.insert("雨夹雪", ":/image/type/YuJiaXue.png");
    mTypeMap.insert("阵雪", ":/image/type/ZhenXue.png");
    mTypeMap.insert("阵雨", ":/image/type/ZhenYu.png");
    mTypeMap.insert("中到大雪", ":/image/type/ZhongDaoDaXue.png");
    mTypeMap.insert("中到大雨", ":/image/type/ZhongDaoDaYu.png");
    mTypeMap.insert("中雪", ":/image/type/ZhongXue.png");
    mTypeMap.insert("中雨", ":/image/type/ZhongYu.png");

    //3网络请求
    mNetworkAccessManager = new QNetworkAccessManager(this);
    connect(mNetworkAccessManager, &QNetworkAccessManager::finished, this, &MainWindow::onReplied);

    //直接在构造中，请求天气数据
    //北京的城市编码"101010100"
//    getWeatherInfo("101280101");//广州
    getWeatherInfo("北京");

    //4高低温曲线，给标签添加事件过滤器
    ui->lblHighCurve->installEventFilter(this);
    ui->lblLowCurve->installEventFilter(this);
    //标签有事件发送时，被当前窗口this拦截，调用重写的eventFilter，是高温的就绘制高温

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::contextMenuEvent(QContextMenuEvent *event)//重写父类右键菜单事件
{
    //弹出右键菜单
    mExitMenu->exec(QCursor::pos());//点击位置传给菜单
}

void MainWindow::mousePressEvent(QMouseEvent *ev)
{
    //鼠标与应用窗口左上角的距离 = 鼠标与显示屏左上角的距离 - 应用窗口与显示屏左上角的距离
    mOffset = ev->globalPosition().toPoint() - this->pos();
}

void MainWindow::mouseMoveEvent(QMouseEvent *ev)
{
    //设置应用窗口与显示屏左上角的距离
    //鼠标与显示屏左上角的距离-鼠标与应用窗口左上角的距离
    this->move(ev->globalPosition().toPoint() - mOffset);
}

void MainWindow::getWeatherInfo(QString cityName)
{
    QString cityCode = WeatherTool::getCityCode(cityName);
    if(cityCode.isEmpty()){
        QMessageBox::warning(this, "城市", "请检查输入是否输入正确！");
    }
    QUrl url("http://t.weather.itboy.net/api/weather/city/" + cityCode);
    //调用get请求，finished执行 void onReplied(QNetworkReply* reply);
    mNetworkAccessManager->get(QNetworkRequest(url));
}

void MainWindow::onReplied(QNetworkReply *reply)
{
    //    qDebug() << "onReplied success";
    //数据都在reply里
    //响应码 200为成功

    int status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    //    qDebug() << "operation:" <<reply->operation();
    //    qDebug() << "status_code:" <<status_code;
    //    qDebug() << "url:" <<reply->url();
    //    qDebug() << "raw header:" <<reply->rawHeaderList();

    if(reply->error() != QNetworkReply::NoError || status_code != 200){
        qDebug() << reply->errorString().toLatin1().data();
    }
    else{
        QByteArray byteArray = reply->readAll();
        qDebug() << "read all:" << byteArray.data(); //json.cn解析

        parseJson(byteArray);
    }
    reply->deleteLater();
}

void MainWindow::parseJson(QByteArray &byteArray)
{
    QJsonParseError err;
    QJsonDocument doc = QJsonDocument::fromJson(byteArray, &err);
    if(err.error != QJsonParseError::NoError){
        return;
    }
    //根据json.cn信息
    QJsonObject rootObject = doc.object();
    //获取第一个"message"看能否获取到
    qDebug() << rootObject.value("message").toString();

    //1解析日期和城市
    mToday.date = rootObject.value("date").toString();
    mToday.city = rootObject.value("cityInfo").toObject().value("city").toString();

    //2解析yesterday
    QJsonObject objData = rootObject.value("data").toObject();
    QJsonObject objYesterday = objData.value("yesterday").toObject();
    mDay[0].week = objYesterday.value("week").toString();
    mDay[0].date = objYesterday.value("ymd").toString();
    mDay[0].type = objYesterday.value("type").toString();

    QString s;
    s = objYesterday.value("high").toString().split(" ").at(1);//温度℃
    s = s.left(s.length()-1);
    mDay[0].high = s.toInt();
    s = objYesterday.value("low").toString().split(" ").at(1);//温度℃
    s = s.left(s.length()-1);
    mDay[0].low = s.toInt();

    mDay[0].fx = objYesterday.value("fx").toString();
    mDay[0].fl = objYesterday.value("fl").toString();

    mDay[0].aqi = objYesterday.value("aqi").toDouble();

    //3解析forcast中5天的数据
    QJsonArray forecastArray = objData.value("forecast").toArray();
    for(int i = 0; i < 5; i++){
        QJsonObject objForecast = forecastArray[i].toObject();
        mDay[i + 1].week = objForecast.value("week").toString();
        mDay[i + 1].date = objForecast.value("ymd").toString();
        mDay[i + 1].type = objForecast.value("type").toString();

        QString s;
        s = objForecast.value("high").toString().split(" ").at(1);//温度℃
        s = s.left(s.length()-1);
        mDay[i + 1].high = s.toInt();
        s = objForecast.value("low").toString().split(" ").at(1);//温度℃
        s = s.left(s.length()-1);
        mDay[i + 1].low = s.toInt();

        mDay[i + 1].fx = objForecast.value("fx").toString();
        mDay[i + 1].fl = objForecast.value("fl").toString();

        mDay[i + 1].aqi = objForecast.value("aqi").toDouble();
    }

    //4解析今天的数据
    mToday.ganmao = objData.value("ganmao").toString();
    mToday.wendu = objData.value("wendu").toString().toInt();
    mToday.shidu = objData.value("shidu").toString();
    mToday.pm25 = objData.value("pm25").toDouble();
    mToday.quality = objData.value("quality").toString();

    //5forcast中第一个数据也是今天的数据
    mToday.type = mDay[1].type;

    mToday.fx = mDay[1].fx;
    mToday.fl = mDay[1].fl;

    mToday.high = mDay[1].high;
    mToday.low = mDay[1].low;

    //6更新ui
    updateUI();

    //7更新温度曲线
    ui->lblHighCurve->update();
    ui->lblLowCurve->update();
}

void MainWindow::updateUI()
{
    //1更新日期和城市
    ui->lblDate->setText(QDateTime::fromString(mToday.date, "yyyyMMdd").toString("yyyy/MM/dd") + " " + mDay[1].week);
    ui->lblCity->setText(mToday.city);
    //2更新今天
    ui->lblTemp->setText(QString::number(mToday.wendu));
    ui->lblType->setText(mToday.type);
    ui->lblTypeIcon->setPixmap(mTypeMap[mToday.type]);
    ui->lblLowHigh->setText(QString::number(mToday.low) + "~" + QString::number(mToday.high) + "℃");
    ui->lblGanMao->setText("感冒指数：" + mToday.ganmao);
    ui->lblWindFX->setText(mToday.fx);
    ui->lblWindFL->setText(mToday.fl);
    ui->lblPM25->setText(QString::number(mToday.pm25));
    ui->lblShiDu->setText(mToday.shidu);
    ui->lblQuality->setText(mToday.quality);

    //3更新六天
    for(int i = 0; i < 6; i++){
        mWeekList[i]->setText("周" + mDay[i].week.right(1));
        ui->lblWeek_1->setText("昨天");
        ui->lblWeek_2->setText("今天");
        ui->lblWeek_3->setText("明天");

        QStringList ymdList = mDay[i].date.split("-");
        mDateList[i]->setText(ymdList[1] + "/" + ymdList[2]);

        mTypeList[i]->setText(mDay[i].type);
        mTypeIconList[i]->setPixmap(mTypeMap[mDay[i].type]);

        if(mDay[i].aqi >= 0 && mDay[i].aqi <= 50){
            mAqiList[i]->setText("优");
            mAqiList[i]->setStyleSheet("background-color: rgb(121, 184, 0);");
        }
        else if(mDay[i].aqi > 50 && mDay[i].aqi <= 100){
            mAqiList[i]->setText("良");
            mAqiList[i]->setStyleSheet("background-color: rgb(255, 187, 23);");
        }
        else if(mDay[i].aqi > 100 && mDay[i].aqi <= 150){
            mAqiList[i]->setText("轻度");
            mAqiList[i]->setStyleSheet("background-color: rgb(255, 87, 97);");
        }
        else if(mDay[i].aqi > 150 && mDay[i].aqi <= 200){
            mAqiList[i]->setText("中度");
            mAqiList[i]->setStyleSheet("background-color: rgb(235, 17, 27);");
        }
        else if(mDay[i].aqi > 200 && mDay[i].aqi <= 250){
            mAqiList[i]->setText("重度");
            mAqiList[i]->setStyleSheet("background-color: rgb(170, 0, 0);");
        }
        else{
            mAqiList[i]->setText("严重");
            mAqiList[i]->setStyleSheet("background-color: rgb(110, 0, 0);");
        }

        mFxList[i]->setText(mDay[i].fx);
        mFlList[i]->setText(mDay[i].fl);


    }

}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == ui->lblHighCurve && event->type() == QEvent::Paint){
        paintHighCurve();
    }
    if(watched == ui->lblLowCurve && event->type() == QEvent::Paint){
        paintLowCurve();
    }
    //其他控件默认处理
    return QWidget::eventFilter(watched, event);
}

void MainWindow::paintHighCurve()
{
    QPainter painter(ui->lblHighCurve);
    //抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);

    //1获取x坐标 (6个标签的x中点)
    int pointX[6] = {0};
    for(int i = 0; i < 6; i++){
        pointX[i] = mWeekList[i]->pos().x() + mWeekList[i]->width()/2;
    }

    //2获取y坐标(6天平均值为y中点，比平均值高的往上画)
    int tempSum = 0;
    int tempAverage = 0;
    for(int i = 0; i < 6; i++){
        tempSum += mDay[i].high;
    }
    tempAverage = tempSum/6;
    int pointY[6] = {0};
    int yCenter = ui->lblHighCurve->height()/2;
    for(int i = 0; i < 6; i++){
        pointY[i] = yCenter - ((mDay[i].high-tempAverage) * INCREMENT);
    }

    //3绘制
    QPen pen = painter.pen();
    pen.setWidth(1);
    pen.setColor(QColor(255,170,0));

    painter.setPen(pen);
    painter.setBrush(QColor(255,170,0)); //画刷设置内部填充

    for(int i = 0; i < 6; i++){
        //画点
        painter.drawEllipse(QPoint(pointX[i], pointY[i]), POINT_RADIUS, POINT_RADIUS);
        //温度文本
        painter.drawText(pointX[i] - TEXT_OFFSET_X ,pointY[i] - TEXT_OFFSET_Y, QString::number(mDay[i].high) + "℃");
    }
    //画线
    for(int i = 0; i < 5; i++){
        if(i == 0){
            pen.setStyle(Qt::DotLine);//昨天与今天的用虚线
            painter.setPen(pen);
        }
        else{
            pen.setStyle(Qt::SolidLine);//实线
            painter.setPen(pen);
        }
        painter.drawLine(pointX[i], pointY[i], pointX[i + 1], pointY[i + 1]);
    }
}

void MainWindow::paintLowCurve()
{
    QPainter painter(ui->lblLowCurve);
    //抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);

    //1获取x坐标 (6个标签的x中点)
    int pointX[6] = {0};
    for(int i = 0; i < 6; i++){
        pointX[i] = mWeekList[i]->pos().x() + mWeekList[i]->width()/2;
    }

    //2获取y坐标(6天平均值为y中点，比平均值高的往上画
    int tempSum = 0;
    int tempAverage = 0;
    for(int i = 0; i < 6; i++){
        tempSum += mDay[i].low;
    }
    tempAverage = tempSum/6;
    int pointY[6] = {0};
    int yCenter = ui->lblLowCurve->height()/2;
    for(int i = 0; i < 6; i++){
        pointY[i] = yCenter - ((mDay[i].low-tempAverage) * INCREMENT);
    }

    //3绘制
    QPen pen = painter.pen();
    pen.setWidth(1);
    pen.setColor(QColor(0,255,240));

    painter.setPen(pen);
    painter.setBrush(QColor(0,255,240)); //画刷设置内部填充

    for(int i = 0; i < 6; i++){
        //画点
        painter.drawEllipse(QPoint(pointX[i], pointY[i]), POINT_RADIUS, POINT_RADIUS);
        //温度文本
        painter.drawText(pointX[i] - TEXT_OFFSET_X ,pointY[i] - TEXT_OFFSET_Y, QString::number(mDay[i].low) + "℃");
    }
    //画线
    for(int i = 0; i < 5; i++){
        if(i == 0){
            pen.setStyle(Qt::DotLine);//虚线
            painter.setPen(pen);
        }else{
            pen.setStyle(Qt::SolidLine);//虚线
            painter.setPen(pen);
        }
         painter.drawLine(pointX[i], pointY[i], pointX[i + 1], pointY[i + 1]);
    }
}


//void MainWindow::paintEvent(QPaintEvent *)//圆角窗口
//{
//    QStyleOption opt;
//    opt.initFrom(this);
//    QPainter painter(this);
//    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
//}


void MainWindow::on_btnSearch_clicked()
{
    QString cityName = ui->letSearch->text();
    getWeatherInfo(cityName);
}

